/*
 * link_list.h
 *
 *  Created on: Aug 31, 2012
 *      Author: root
 */

#ifndef LINK_LIST_H_
#define LINK_LIST_H_

/*
*T must define for eg:
*struct node{
*       xxxx xxxx;your struct member
*       node * next;
*   node * prev;
*};
*/
enum LINK_LIST_TYPE
{
        LINK_FILO,
        LINK_FIFO
};
/*du_link list template*/
template <class T>
class link_list
{
public:
        link_list()
        {
                count = 0;
                list_head = NULL;
                list_tail = NULL;
                type = LINK_FILO;
        }

        ~link_list(void)
        {
                if(list_head != NULL)
                {
                        if(list_head->next != NULL)
                        {
                                list_head->next->prev = NULL;
                                list_head->next = NULL;
                        }

                        delete list_head;
                        list_head = NULL;
                        list_tail = NULL;
                }
        }

public:
        int size(void)
        {
                return count;
        }

        bool init_list(bool is_can_remove,LINK_LIST_TYPE link_type = LINK_FILO)
        {
                can_remove = is_can_remove;
                type = link_type;
                list_head = new T ();

                if(list_head == NULL)
                {
                        return false;
                }
                else
                {
                        list_head->next = list_head->prev = NULL;
                        list_tail = list_head;
                }

                return true;
        }

        T  * get_first(void)
        {
                if(NULL == list_head)
                        return NULL;
                else
                        return list_head->next;
        }

        bool push(T  * node)
        {
                if(node == NULL)
                        return false;

                node->prev = node->next = NULL;

                /*header insert*/
                if(type == LINK_FIFO)
                {
                        if(list_head->next != NULL)
                        {
                                node->next = list_head->next;
                                list_head->next->prev = node;
                                list_head->next = node;
                                node->prev = list_head;
                        }
                        else
                        {
                                list_head->next = node;
                                node->prev = list_head;
                        }
                }
                else
                {
                        /*tail insert*/
                        list_tail->next = node;
                        node->prev = list_tail;
                        list_tail = node;
                }

                count++;
                return true;
        }

        bool remove(T  *node)
        {
                if(!can_remove || node == NULL || count <= 0)
                        return false;

                if(node == list_head)
                        return false;

                if(node->prev == NULL)
                        return false;

                /*check is list tail*/
                if(list_tail == node)
                {
                        list_tail = node->prev;
                }

                /*remove node*/
                node->prev->next = node->next;
                if(node->next!= NULL)
                        node->next->prev = node->prev;
                node->prev = node->next = NULL;

                count--;
                return true;
        }

        bool alloc(T  **node)
        {
                if(can_remove || count<=0)
                        return false;

                *node = list_head->next;
                if(*node == NULL)
                        return false;

                if(list_head->next->next!=NULL)
                {
                        list_head->next->next->prev = list_head;
                        list_head->next = list_head->next->next;
                }
                else
                {
                        list_head->next = NULL;
                }

                /*check is list tail*/
                if(list_tail == (*node))
                {
                        list_tail = list_head;
                }

                (*node)->next = (*node)->prev = NULL;
                count--;
                return true;
        }

private:
        int count;
        bool can_remove;
        LINK_LIST_TYPE type;
        T  *list_head;
        T  *list_tail;
};


#endif /* LINK_LIST_H_ */
